package com.bear.fastrepair.utils

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.viewbinding.ViewBinding
import com.bear.fastrepair.base.BearApplication
import java.lang.reflect.ParameterizedType

object ViewBindingHelper {
    @Suppress("UNCHECKED_CAST")
    @JvmName("inflateWithGeneric")
    fun <VB : ViewBinding> Any.inflateBindingWithGeneric(layoutInflater: LayoutInflater): VB =
        withGenericBindingClass(this) {
            it.getMethod("inflate", LayoutInflater::class.java).invoke(null, layoutInflater) as VB
        }

    @Suppress("UNCHECKED_CAST")
    @JvmName("inflateWithGeneric")
    fun <VB : ViewBinding> Any.inflateBindingWithGeneric(view: View): VB =
        withGenericBindingClass(this) {
            it.getMethod("bind", LayoutInflater::class.java).invoke(null, view) as VB
        }

    @JvmName("inflateWithGeneric")
    fun <VB : ViewBinding> Any.inflateBindingWithGeneric(parent: ViewGroup): VB =
        withGenericBindingClass(this) {
            inflateBinding(
                it,
                LayoutInflater.from(parent.context),
                parent,
                false
            )
        }

    @JvmName("inflateWithGeneric")
    fun <VB : ViewBinding> Any.inflateBindingWithGeneric(
        layoutInflater: LayoutInflater, parent: ViewGroup?, attachToParent: Boolean
    ): VB =
        withGenericBindingClass(this) { inflateBinding(it, layoutInflater, parent, attachToParent) }

    @Suppress("UNCHECKED_CAST")
    private fun <VB : ViewBinding> inflateBinding(
        clazz: Class<VB>,
        layoutInflater: LayoutInflater,
        parent: ViewGroup?,
        attachToParent: Boolean
    ) = clazz.getMethod(
        "inflate",
        LayoutInflater::class.java,
        ViewGroup::class.java,
        Boolean::class.java
    ).invoke(null, layoutInflater, parent, attachToParent) as VB

    private inline fun <VB : ViewBinding> withGenericBindingClass(
        any: Any,
        block: (Class<VB>) -> VB
    ): VB {
        var index = 0
        while (true) {
            try {
                return block(any.findGenericBindingClass(index))
            } catch (e: NoSuchMethodException) {
                index++
            }
        }
    }

    @Suppress("UNCHECKED_CAST")
    private fun <VB : ViewBinding> Any.findGenericBindingClass(index: Int): Class<VB> {
        val type = javaClass.genericSuperclass
        if (type is ParameterizedType && index < type.actualTypeArguments.size) {
            return type.actualTypeArguments[index] as Class<VB>
        }
        throw IllegalArgumentException("Generic ViewBinding not found!!!")
    }
}

object SharedPreferencesHelper {
    private val sp by lazy {
        BearApplication.getApplication()?.getSharedPreferences("bear_info", Context.MODE_PRIVATE)
    }

    private val spEditor by lazy { sp?.edit() }

    fun <T> putInfo(key: String, value: T): Boolean? = when (value) {
        is Int -> spEditor?.putInt(key, value)
        is String -> spEditor?.putString(key, value)
        is Long -> spEditor?.putLong(key, value)
        is Float -> spEditor?.putFloat(key, value)
        is Boolean -> spEditor?.putBoolean(key, value)
        else -> null
    }?.commit()

    fun getIntNormal(key: String): Int? = sp?.getInt(key, -1)
    suspend fun getInt(key: String): Int? = sp?.getInt(key, -1)
    fun getBoolean(key: String): Boolean? = sp?.getBoolean(key, false)
    suspend fun getString(key: String): String? = sp?.getString(key, "")
    fun getStringNormal(key: String): String? = sp?.getString(key, "")
    fun getLong(key: String): Long? = sp?.getLong(key, -1)
    fun getFloat(key: String): Float? = sp?.getFloat(key, -1f)

    fun clear() = spEditor?.let {
        it.clear()
        it.commit()
    }
}